package com.ws.client.feign;

import com.ws.client.controller.XmlUtils;
import feign.codec.Decoder;
import feign.codec.EncodeException;
import feign.codec.Encoder;
import feign.jaxb.JAXBContextFactory;
import feign.soap.SOAPDecoder;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringEscapeUtils;
import org.springframework.context.annotation.Bean;
import org.w3c.dom.Document;
import org.w3c.dom.Element;

import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.soap.*;
import javax.xml.transform.TransformerFactoryConfigurationError;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;

import static javax.xml.soap.SOAPConstants.DEFAULT_SOAP_PROTOCOL;

@Slf4j
public class PsucsFeignClientConfiguration {

    private Charset charsetEncoding = StandardCharsets.UTF_8;
    private String soapProtocol = DEFAULT_SOAP_PROTOCOL;

    private static final JAXBContextFactory jaxbContextFactory = new JAXBContextFactory.Builder()
            .withMarshallerJAXBEncoding("UTF-8")
            .build();

    /**
     * 新供指挥
     * <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:wec="http://wechat.psucs.com">
     *     <soapenv:Header/>
     *     <soapenv:Body>
     *         <wec:$method>
     *             <!--Optional:-->
     *             <wec:msg>$param</wec:msg>
     *         </wec:$method>
     *     </soapenv:Body>
     * </soapenv:Envelope>
     * @return
     */
    @Bean
    public Encoder feignEncoder() {
        return (object, bodyType, template) -> {
            if (!(bodyType instanceof Class)) {
                throw new UnsupportedOperationException(
                        "SOAP only supports encoding raw types. Found " + bodyType);
            }
            try {
                Document document = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();
                Marshaller marshaller = jaxbContextFactory.createMarshaller((Class<?>) bodyType);
                // 格式化xml输出的格式
                marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT,
                        Boolean.TRUE);
                marshaller.marshal(object, document);
                Element rootElement = document.getDocumentElement();
                String xmlParam = XmlUtils.convertToXml(object);
                //创建soap工厂
                SOAPFactory soapFactory = SOAPFactory.newInstance();

                SOAPMessage soapMessage = MessageFactory.newInstance(soapProtocol).createMessage();
                SOAPEnvelope soapEnvelope = soapMessage.getSOAPPart().getEnvelope();
                //自定义前缀
                soapEnvelope.setPrefix("soapenv");
                soapEnvelope.removeNamespaceDeclaration("SOAP-ENV");
                soapEnvelope.addNamespaceDeclaration("wec", "http://wechat.psucs.com");
                soapMessage.setProperty(SOAPMessage.CHARACTER_SET_ENCODING, charsetEncoding.displayName());
                Name msg = soapEnvelope.createName("msg","wec",null);
                Name method = soapEnvelope.createName("testMethod","wec","http://wechat.psucs.com");
                //soapMessage.getSOAPBody().addDocument(document);

                //添加消息体以及json字符串
                SOAPBody body = soapMessage.getSOAPBody();
                body.setPrefix("soapenv");
                SOAPBodyElement bodyElement = body.addBodyElement(method);
                SOAPElement msgBody = bodyElement.addChildElement("msg","wec");
                msgBody.addNamespaceDeclaration("wec","http://wechat.psucs.com");
                SOAPElement requestData = soapFactory.createElement(rootElement);
                msgBody.addChildElement(requestData);
               // msgBody.addTextNode(judgeNull(xmlParam));
//                SOAPElement methodElement = soapFactory.createElement(method);
//                SOAPElement msgBody = soapFactory.createElement(msg);
//                SOAPElement requestData = soapFactory.createElement(rootElement);
//                msgBody.addChildElement(requestData);
//                methodElement.addChildElement(msgBody);
//                body.addChildElement(methodElement);
                //添加信息头内容
                SOAPHeader header = soapEnvelope.getHeader();
                header.setPrefix("soapenv");
                SOAPElement wsHeaderElm = soapFactory.createElement("HEADER", "wec", "http://wechat.psucs.com");
                SOAPElement svcnameElm = soapFactory.createElement("SVCNAME");
                wsHeaderElm.addChildElement(svcnameElm);
                header.addChildElement(wsHeaderElm);
                soapMessage.saveChanges();
                ByteArrayOutputStream bos = new ByteArrayOutputStream();
                soapMessage.writeTo(bos);
                String outParam = new String(bos.toByteArray(),StandardCharsets.UTF_8.toString());
                System.out.println(outParam);
                System.out.println(StringEscapeUtils.unescapeHtml(outParam));
                System.out.println(outParam.replaceAll("ORDER", "cov:ORDER"));
                template.body(outParam.replaceAll("CovRequest", "cov:CovRequest"));
            } catch (SOAPException | JAXBException | ParserConfigurationException | IOException | TransformerFactoryConfigurationError e) {
                e.printStackTrace();
                throw new EncodeException(e.toString(), e);
            }
        };
    }

    @Bean
    public Decoder feignDecoder() {
        return new SOAPDecoder(jaxbContextFactory);
    }

    public static  String  judgeNull(String str){
        return (str==null)?"":str;
    }
}


